﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.Collections.ObjectModel;
using System.Xml;
using System.Xml.XPath;

namespace XMM
{
    /// <summary>
    /// Interaktionslogik für Window1.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public bool SubItemSelected
        {
            get
            {
                return IsSubItemSelected;
            }
        }

        private bool IsSubItemSelected = false;

        XMMDBDataContext dbConnection = null;

        public bool IsDatabaseAvailable { get; set; }

        Mutex mutUpdateGUI = new Mutex();

        Settings oSettings = new Settings();

        public Objects.Audition SelectedAudition { get; set; }

        private bool bMoviesLoaded = false;
        private bool bSeriesLoaded = false;

        ObservableCollection<Objects.PlaybackHistoryRecord> _SelectedItemHistory = new ObservableCollection<Objects.PlaybackHistoryRecord>();

        public ObservableCollection<Objects.PlaybackHistoryRecord> SelectedItemHistory
        { get { return _SelectedItemHistory; } }

        public MainWindow()
        {
            InitializeComponent();

            IsDatabaseAvailable = false;
            IsPlaying = false;

            // Check for MediaLibrary-Path.
            Tools.checkMediaLibraryPath();
        }

        private void mitExit_Click(object sender, RoutedEventArgs e)
        {
            Shutdown();
        }

        /// <summary>
        /// Shutdown all Playback-Activies, save progress, update DB and EXIT.
        /// </summary>
        /// <returns>[bool] true if shutdown is clean.</returns>
        public void Shutdown()
        {
            try
            {
                // NEED MORE CODE


                // EXIT
                Environment.Exit(0);
            }
            catch (Exception ex)
            {

            }
        }

        private Image imgMovies;
        private Image imgSeries;
        private Image imgMusic;
        private Image imgPictures;
        private Label lblMovies;
        private Label lblSeries;
        private Label lblMusic;
        private Label lblPictures;

        private Thread thLoadAuditions;

        /// <summary>
        /// Initialize Data.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            RefreshXMM();
        }

        public void RefreshXMM()
        {
            lvBrowser_left.ItemsSource = null;
            lvBrowser_left.Items.Clear();

            /*
            // Change connection-string if neccessary.
            System.Configuration.ConnectionStringSettings oConnection = System.Configuration.ConfigurationManager.ConnectionStrings[0];
            oConnection.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|" + oSettings.DatabaseStoragePath + ";Integrated Security=True;Connect Timeout=30;User Instance=True";
            */

            updateConnectionString();

            updateLibraryTopItems();
            testConnection();

            // Load Auditions.
            thLoadAuditions = new Thread(new ThreadStart(loadAuditions));
            thLoadAuditions.Start();

            // Load Movies.
            loadMovies();

            // Load Series.
            loadSeries();
        }

        public void updateConnectionString()
        { 

            // Check if DB-File specified in settings.xml exists.
            if (oSettings.DatabaseStoragePath != "\\XMM.mdf")
            {
                if (System.IO.File.Exists(oSettings.DatabaseStoragePath) == false)
                {
                    MessageBox.Show("Die Datei \"" + oSettings.DatabaseStoragePath + "\" wurde nicht gefunden! Die Datenbank kann nicht geladen werden!", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
            }
            else
            {
                if (System.IO.File.Exists(Tools.getInstallationPath() + "XMM.mdf") == false)
                {
                    MessageBox.Show("Die Datei \"" + Tools.getInstallationPath() + "XMM.mdf\" wurde nicht gefunden! Die Datenbank kann nicht geladen werden!", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
            }

            /**********************************
             * Build new ConnectionString
             * */
            string sNewConnectionString = String.Empty;

            // Build ConnectionString according to location.
            if(oSettings.DatabaseStoragePath == "\\XMM.mdf")
                sNewConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|" + oSettings.DatabaseStoragePath + @";Integrated Security=True;Connect Timeout=30;User Instance=True";
            else
                sNewConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=" + oSettings.DatabaseStoragePath + @";Integrated Security=True;Connect Timeout=30;User Instance=True";

            try
            {
                // Open XMM.exe.Config as XML-File.
                XmlDocument xdApplicationConfig = new XmlDocument();
                xdApplicationConfig.Load(Tools.getInstallationPath() + "XMM.exe.config");

                // Load <connectionStrings>-Section.
                XmlNode xnConnectionStrings = xdApplicationConfig.DocumentElement.SelectSingleNode("//connectionStrings");

                // Remove existing connection-string.
                if (xnConnectionStrings != null && xnConnectionStrings.ChildNodes.Count > 0)
                {
                    //xnConnectionStrings.InnerXml.Remove(0);
                    xnConnectionStrings.RemoveAll();
                }

                // Build new Connection-String-Element (<add...>).
                XmlNode xnNewConnectionString = xdApplicationConfig.CreateNode(XmlNodeType.Element, "add", "");
                XmlAttribute xaName = xdApplicationConfig.CreateAttribute("name");
                xaName.InnerText = "XMM.Properties.Settings.XMMConnectionString";
                XmlAttribute xaNewConnectionStringProvider = xdApplicationConfig.CreateAttribute("providerName");
                xaNewConnectionStringProvider.InnerText = "System.Data.SqlClient";
                XmlAttribute xaNewConnectionStringValue = xdApplicationConfig.CreateAttribute("connectionString");
                xaNewConnectionStringValue.InnerText = sNewConnectionString;
                
                // Add Attributes to Element.
                xnNewConnectionString.Attributes.Append(xaName);
                xnNewConnectionString.Attributes.Append(xaNewConnectionStringProvider);
                xnNewConnectionString.Attributes.Append(xaNewConnectionStringValue);
                
                // Add new Connection-String to <connectionStrings>-Section
                //xnConnectionStrings.AppendChild(xnNewConnectionString);
                xnConnectionStrings.PrependChild(xnNewConnectionString);

                // Save changes to XMM.exe.config.
                xdApplicationConfig.Save(Tools.getInstallationPath() + "XMM.exe.config");
            }
            catch (Exception ex)
            {
                MessageBox.Show("Fehler beim Aktualisieren des Datenbank-Verbindungs-Strings: " + ex.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void loadAuditions()
        {
            if (mutUpdateGUI.WaitOne(1000))
            {
                try
                {
                    this.Dispatcher.Invoke(new updateStatusCallback(updateStatus), new object[] { "Lade Zuseher...", true });
                    this.Dispatcher.Invoke(new clearAuditionsCallback(clearAuditions));

                    List<Objects.Audition> lAuditions = Objects.Audition.getAllAuditions();

                    if (lAuditions != null && lAuditions.Count > 0)
                    {
                        foreach (Objects.Audition oAudition in lAuditions)
                        {
                            this.Dispatcher.Invoke(new addAuditionCallback(this.addAudition), new object[] { oAudition });
                        }
                    }

                    // Select last Audition if available.
                    if (oSettings.LastAuditionID != 0)
                    {
                        this.Dispatcher.Invoke(new selectAuditionCallback(this.selectAudition), new object[] { oSettings.LastAuditionID });
                    }

                    this.Dispatcher.Invoke(new updateStatusCallback(updateStatus), new object[] { "Bereit...", false });
                }
                catch(Exception ex)
                {
                    MessageBox.Show("Fehler beim Laden der Zuseher: " + ex.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                }
                mutUpdateGUI.ReleaseMutex();
            }
        }

        private void selectAudition(int iAuditionID)
        {
            Objects.Audition oAudition = new XMM.Objects.Audition(iAuditionID);

            if (oAudition != null && oAudition.AuditionID != 0)
            {
                cmbAuditionSelection.SelectedIndex = cmbAuditionSelection.Items.IndexOf(oAudition);
                cmbAuditionSelection.Text = oAudition.Name;
                SelectedAudition = oAudition;
            }
        }

        private delegate void selectAuditionCallback(int iAuditionID);

        private void clearAuditions()
        {
            cmbAuditionSelection.Items.Clear();
        }

        private delegate void clearAuditionsCallback();

        private void addAudition(Objects.Audition oAudition)
        {
            cmbAuditionSelection.Items.Add(oAudition);
        }

        private delegate void addAuditionCallback(Objects.Audition oAudition);

        public void testConnection()
        {
            try
            {
                if (dbConnection == null)
                {
                    dbConnection = new XMMDBDataContext();
                }

                if (dbConnection.DatabaseExists())
                {
                    IsDatabaseAvailable = true;
                }
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                MessageBox.Show("Die Datenbank-Verbindung kann nicht hergestellt werden: " + ex.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// Setup TreeView-Main-Items.
        /// </summary>
        private void updateLibraryTopItems()
        {
            imgMovies = new Image();
            imgMovies.Source = new BitmapImage(new Uri(@"/images/bin/Movie_64.png", UriKind.Relative));
            imgMovies.Width = imgMovies.Height = 24;
            lblMovies = new Label();
            lblMovies.Content = "Filme";
            lblMovies.FontSize = 14;
            StackPanel spnMovies = new StackPanel();
            spnMovies.Orientation = Orientation.Horizontal;
            spnMovies.Children.Add(imgMovies);
            spnMovies.Children.Add(lblMovies);

            imgSeries = new Image();
            imgSeries.Source = new BitmapImage(new Uri(@"/images/bin/series.png", UriKind.Relative));
            imgSeries.Width = imgSeries.Height = 24;
            lblSeries = new Label();
            lblSeries.Content = "Serien";
            lblSeries.FontSize = 14;
            StackPanel spnSeries = new StackPanel();
            spnSeries.Orientation = Orientation.Horizontal;
            spnSeries.Children.Add(imgSeries);
            spnSeries.Children.Add(lblSeries);

            imgMusic = new Image();
            imgMusic.Source = new BitmapImage(new Uri(@"/images/bin/music.png", UriKind.Relative));
            imgMusic.Width = imgMusic.Height = 24;
            lblMusic = new Label();
            lblMusic.Content = "Musik";
            lblMusic.FontSize = 14;
            StackPanel spnMusic = new StackPanel();
            spnMusic.Orientation = Orientation.Horizontal;
            spnMusic.Children.Add(imgMusic);
            spnMusic.Children.Add(lblMusic);

            imgPictures = new Image();
            imgPictures.Source = new BitmapImage(new Uri(@"/images/bin/pictures.png", UriKind.Relative));
            imgPictures.Width = imgPictures.Height = 24;
            lblPictures = new Label();
            lblPictures.Content = "Bilder & Fotos";
            lblPictures.FontSize = 14;
            StackPanel spnPictures = new StackPanel();
            spnPictures.Orientation = Orientation.Horizontal;
            spnPictures.Children.Add(imgPictures);
            spnPictures.Children.Add(lblPictures);

            tviMovies.Header = spnMovies;
            tviSeries.Header = spnSeries;
            tviMusic.Header = spnMusic;
            tviPictures.Header = spnPictures;
        }

        private void loadSeries()
        {
            /***********************************
                * Clear existing series
                * */
            lvBrowser_left.Items.Clear();
            _SelectedItemHistory.Clear();
            lvBrowser_right.ItemsSource = SelectedItemHistory;
            spnItemDetails.Children.Clear();
            tviSeries.Items.Clear();

            /***********************************
                * LOAD SERIES
                * */

            // Get all Series.
            List<Objects.Series> lAvailableSeries = Objects.Series.getAllSeries();

            if (lAvailableSeries != null && lAvailableSeries.Count > 0)
            {
                foreach (Objects.Series oSeries in lAvailableSeries)
                {
                    TreeViewItem tviShow = new TreeViewItem();
                    tviShow.Header = oSeries.Name;
                    tviShow.Tag = oSeries;

                    tviShow.Selected += new RoutedEventHandler(tviShow_Selected);
                    tviShow.Expanded += new RoutedEventHandler(tviShow_Expanded);

                    if (oSeries.Seasons != null && oSeries.Seasons.Count > 0)
                    {
                        foreach (Objects.SeriesSeason oSeason in oSeries.Seasons)
                        {
                            TreeViewItem tviShowSeason = new TreeViewItem();
                            tviShowSeason.Header = oSeason.ToString();
                            tviShowSeason.Tag = oSeason;
                            tviShowSeason.Selected += new RoutedEventHandler(tviShowSeason_Selected);

                            tviShow.Items.Add(tviShowSeason);
                        }
                    }

                    lvBrowser_left.Items.Add(oSeries);

                    tviSeries.Items.Add(tviShow);
                }
            }
        }

        void tviShow_Expanded(object sender, RoutedEventArgs e)
        {
            // Do Nothing...
        }

        void tviShowSeason_Selected(object sender, RoutedEventArgs e)
        {
            // Get selected Item in Library-TreeView.
            TreeViewItem tviSenderSeason = (TreeViewItem)sender;

            // Derive selected Season from TreeViewItem.
            Objects.SeriesSeason oSeason = (Objects.SeriesSeason)tviSenderSeason.Tag;

            // Load Episodes in lvBrowser_left.
            lvBrowser_left.Items.Clear();
            if (oSeason.Episodes != null && oSeason.Episodes.Count > 0)
            {
                foreach (Objects.SeriesEpisode oEpisode in oSeason.Episodes)
                {
                    ListViewItem lviEpisode = new ListViewItem();
                    lviEpisode.Content = oEpisode.ToString();
                    lviEpisode.Tag = oEpisode;
                    lviEpisode.Selected += new RoutedEventHandler(lviEpisode_Selected);

                    // Check if episode was seen by selected audience.
                    List<Objects.PlaybackHistoryRecord> lPlaybackHistory = Objects.PlaybackHistoryRecord.getAllRecords(2, oEpisode.EpisodeID);
                    bool bWasSeen = false;

                    foreach (Objects.PlaybackHistoryRecord oRecord in lPlaybackHistory)
                    {
                        if (oRecord.AudienceID == SelectedAudition.AuditionID)
                            bWasSeen = true;
                    }

                    if (bWasSeen)
                    {
                        lviEpisode.Content = "√ " + lviEpisode.Content;
                        lviEpisode.Foreground = Brushes.DarkGreen;
                        lviEpisode.FontStyle = FontStyles.Italic;
                    }

                    lvBrowser_left.Items.Add(lviEpisode);
                }
            }
        }

        void lviEpisode_Selected(object sender, RoutedEventArgs e)
        {
            _SelectedItemHistory.Clear();
            ListViewItem lviSender = (ListViewItem)sender;
            Objects.SeriesEpisode oSelectedEpisode = (Objects.SeriesEpisode)lviSender.Tag;

            // Check for valid Episode.
            if (oSelectedEpisode != null)
            {
                // Load Episode-Details.
                spnItemDetails.Children.Clear();

                Controls.Library.Details_Episode ctlEpisode = new Controls.Library.Details_Episode(null, oSelectedEpisode.EpisodeID);
                spnItemDetails.Children.Add(ctlEpisode);

                getEpisodeHistory(oSelectedEpisode);
            }

            lvBrowser_right.ItemsSource = _SelectedItemHistory;
            lvBrowser_right.Items.Refresh();
        }

        private void getEpisodeHistory(Objects.SeriesEpisode oSelectedEpisode)
        {
            // Reset current Playback-History-List...
            _SelectedItemHistory.Clear();

            /*
            // Load Playback-History for current Audience...
            List<Objects.PlaybackHistoryRecord> lPlaybackRecord = Objects.PlaybackHistoryRecord.getAllRecords(2, oSelectedEpisode.EpisodeID);
            if (lPlaybackRecord != null && lPlaybackRecord.Count > 0)
            {
                foreach (Objects.PlaybackHistoryRecord oRecord in lPlaybackRecord)
                {
                    if (oRecord.AudienceID == SelectedAudition.AuditionID)
                        _SelectedItemHistory.Add(oRecord);
                }
            }
             * */

            // Load Playback-History for all Audiences...
            List<Objects.PlaybackHistoryRecord> lPlaybackRecords = Objects.PlaybackHistoryRecord.getAllRecords(2, oSelectedEpisode.EpisodeID);
            if (lPlaybackRecords != null && lPlaybackRecords.Count > 0)
            {
                foreach (Objects.PlaybackHistoryRecord oRecord in lPlaybackRecords)
                {
                    _SelectedItemHistory.Add(oRecord);
                }
            }
        }

        private delegate void getEpisodeHistoryCallback(Objects.SeriesEpisode oSelectedEpisode);

        void tviShow_Selected(object sender, RoutedEventArgs e)
        {
            // Get selected Item in Library-TreeView.
            TreeViewItem tviSenderShow = (TreeViewItem)sender;

            // Derive selected Series from TreeViewItem.
            Objects.Series oShow = (Objects.Series)tviSenderShow.Tag;

            // Load Season int lv_Browser_left.
            lvBrowser_left.Items.Clear();
            if (oShow.Seasons != null && oShow.Seasons.Count > 0)
            {
                foreach (Objects.SeriesSeason oSeason in oShow.Seasons)
                {
                    ListViewItem lviSeason = new ListViewItem();
                    lviSeason.Content = oSeason.ToString();
                    lviSeason.Tag = oSeason;
                    lviSeason.Selected += new RoutedEventHandler(lviSeason_Selected);

                    lvBrowser_left.Items.Add(lviSeason);
                }
            }

            seriesSelected(oShow.SeriesID);
        }

        void lviSeason_Selected(object sender, RoutedEventArgs e)
        {
            // Get selected Item in lvBrowser_left.
            ListViewItem lviSenderSeason = (ListViewItem)sender;

            // Derive selected Season from ListViewItem.
            Objects.SeriesSeason oSeason = (Objects.SeriesSeason)lviSenderSeason.Tag;

            // Load Season-Info into spnItemDetails.
        }

        private void loadMovies()
        {
            lvBrowser_left.Items.Clear();
            //lvBrowser_right.Items.Clear();
            tviMovies.Items.Clear();
            // Populate Movies-List.
            List<Objects.Movie> lMovies = Objects.Movie.getAllMovies(lblStatus, pbStatus);

            if (lMovies != null && lMovies.Count > 0)
            {
                foreach (Objects.Movie oMovie in lMovies)
                {
                    TreeViewItem tviMovie = new TreeViewItem();
                    tviMovie.Tag = oMovie.MovieID;
                    tviMovie.Header = oMovie.Name;
                    tviMovie.Height = 20;
                    tviMovie.Width = 150;
                    if (oMovie.Year != 0)
                        tviMovie.Header += " (" + oMovie.Year.ToString() + ")";

                    tviMovie.Selected += new RoutedEventHandler(tviMovie_Selected);
                    tviMovie.MouseDoubleClick += new MouseButtonEventHandler(tviMovie_MouseDoubleClick);

                    tviMovies.Items.Add(tviMovie);
                }
            }
        }

        void tviMovie_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (IsPlaying)
            {
                MessageBox.Show("Es läuft bereits eine Wiedergabe! Beenden Sie zuerst das laufende Video.", "Parallele Wiedergaben", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                return;
            }

            IsPlaying = true;

            TreeViewItem tviSender = (TreeViewItem)sender;
            Objects.Movie oMovie = new Objects.Movie((Int32)tviSender.Tag);
            Objects.Genre oGenre = new Objects.Genre(oMovie.GenreID);

            updateStatus("Es läuft: " + oMovie.Name + " (" + oGenre.Name + ", " + oMovie.Year + ")", true);

            CurrentPlayback = new Objects.MediaInfo();
            CurrentPlayback.FullPath = oMovie.Files[0].Replace(";", "");
            CurrentPlayback.UserdefinedMediaInfo = oMovie;
            CurrentPlayback.MediaType = 0;

            ParameterizedThreadStart oThreadStart = new ParameterizedThreadStart(startVLCPlayerMovie);
            Thread thMoviePlayback = new Thread(oThreadStart);
            thMoviePlayback.Start(new object[] { oMovie, 0 });
        }

        void tviMovie_Selected(object sender, RoutedEventArgs e)
        {
            // Clear Item Details...
            spnItemDetails.Children.Clear();
            //lvBrowser_left.Items.Clear();
            _SelectedItemHistory.Clear();


            IsSubItemSelected = true;
            Objects.Movie oSelectedMovie = new Objects.Movie((int)((TreeViewItem)sender).Tag);

            if (oSelectedMovie != null && oSelectedMovie.MovieID > 0)
            {
                movieSelected(oSelectedMovie.MovieID);
            }

            getMovieHistory(oSelectedMovie);
        }

        private void tviMovies_Selected(object sender, RoutedEventArgs e)
        {
            if (SubItemSelected == false)
            {
                // Load movies into lvBrowser_left.
                spnItemDetails.Children.Clear();
                lvBrowser_left.Items.Clear();

                List<Objects.Movie> lAvailableMovies = Objects.Movie.getAllMovies(lblStatus, pbStatus);

                if (lAvailableMovies != null && lAvailableMovies.Count > 0)
                {
                    foreach (Objects.Movie oMovie in lAvailableMovies)
                    {
                        ListViewItem lviMovie = new ListViewItem();
                        lviMovie.Content = oMovie.Name;
                        if (oMovie.Files.Count != 0)
                        {
                            lviMovie.Content += " (" + oMovie.Year.ToString() + ")";
                            lviMovie.Tag = oMovie.MovieID;
                            lviMovie.Selected += new RoutedEventHandler(lviMovie_Selected);
                            lviMovie.MouseDoubleClick += new MouseButtonEventHandler(lviMovie_MouseDoubleClick);
                        }

                        lvBrowser_left.Items.Add(lviMovie);
                    }
                }
            }

            IsSubItemSelected = false;
        }

        void lviMovie_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (IsPlaying)
            {
                MessageBox.Show("Es läuft bereits eine Wiedergabe! Beenden Sie zuerst das laufende Video.", "Parallele Wiedergaben", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                return;
            }

            IsPlaying = true;

            ListViewItem lviSender = (ListViewItem)sender;
            Objects.Movie oMovie = new Objects.Movie((Int32)lviSender.Tag);
            Objects.Genre oGenre = new Objects.Genre(oMovie.GenreID);

            updateStatus("Es läuft: " + oMovie.Name + " (" + oGenre.Name + ", " + oMovie.Year + ")", true);

            CurrentPlayback = new Objects.MediaInfo();
            CurrentPlayback.FullPath = oMovie.Files[0].Replace(";", "");
            CurrentPlayback.UserdefinedMediaInfo = oMovie;
            CurrentPlayback.MediaType = 0;

            ParameterizedThreadStart oThreadStart = new ParameterizedThreadStart(startVLCPlayerMovie);
            Thread thMoviePlayback = new Thread(oThreadStart);
            thMoviePlayback.Start(new object[] { oMovie, 0 });
        }

        void lviMovie_Selected(object sender, RoutedEventArgs e)
        {
            ListViewItem lviSelectedMovie = (ListViewItem)sender;
            movieSelected((int)lviSelectedMovie.Tag);
        }

        private void lvBrowser_left_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (tvLibrary.SelectedItem == tviMovies)
            {
                if (lvBrowser_left.SelectedItem != null && ((Control)lvBrowser_left.SelectedItem).Tag != null)
                {
                    // Get Item-Info.
                    ListViewItem lviSelectedMovie = (ListViewItem)lvBrowser_left.SelectedItem;
                    Controls.Library.Details_Movie ctlMovieDetails = new XMM.Controls.Library.Details_Movie((int)lviSelectedMovie.Tag);
                    ctlMovieDetails.Width = spnItemDetails.Width;
                    ctlMovieDetails.Height = spnItemDetails.Height;
                    ctlMovieDetails.Margin = new System.Windows.Thickness(0);
                    spnItemDetails.Children.Clear();
                    spnItemDetails.Children.Add(ctlMovieDetails);

                    getMovieHistory(new Objects.Movie((int)lviSelectedMovie.Tag));
                }
                else
                {
                    spnItemDetails.Children.Clear();
                }
            }
        }

        private void getMovieHistory(Objects.Movie oSelectedMovie)
        {
            // Get Playback-History.
            _SelectedItemHistory = new ObservableCollection<Objects.PlaybackHistoryRecord>();
            List<Objects.PlaybackHistoryRecord> oPlaybackHistory = Objects.PlaybackHistoryRecord.getAllRecords(1, oSelectedMovie.MovieID);
            foreach (Objects.PlaybackHistoryRecord oRecord in oPlaybackHistory)
            {
                _SelectedItemHistory.Add(oRecord);
            }
            lvBrowser_right.ItemsSource = SelectedItemHistory;
            lvBrowser_right.Items.Refresh();
        }

        private delegate void getMovieHistoryCallback(Objects.Movie oSelectedMovie);

        /// <summary>
        /// Load the selected movie into details-panel.
        /// </summary>
        /// <param name="iMovieID"></param>
        private void movieSelected(int iMovieID)
        {
            Controls.Library.Details_Movie ctlMovieDetails = new XMM.Controls.Library.Details_Movie(iMovieID);
            spnItemDetails.Children.Clear();
            spnItemDetails.Children.Add(ctlMovieDetails);
            ctlMovieDetails.HorizontalAlignment = HorizontalAlignment.Stretch;
            ctlMovieDetails.VerticalAlignment = VerticalAlignment.Stretch;
        }

        private void seriesSelected(int iSeriesID)
        {
            Controls.Library.Details_Series ctlSeriesDetails = new Controls.Library.Details_Series(iSeriesID);
            spnItemDetails.Children.Clear();
            spnItemDetails.Children.Add(ctlSeriesDetails);
            ctlSeriesDetails.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            ctlSeriesDetails.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
        }

        /// <summary>
        /// Start Add-New-Folder-Dialog.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mitAddFolder_Click(object sender, RoutedEventArgs e)
        {
            //ImportMedia dlgMediaImporter = new ImportMedia(this);
            //dlgMediaImporter.ShowDialog();
        }

        private void tviSeries_Selected(object sender, RoutedEventArgs e)
        {
            // Clear Item Details...
            //spnItemDetails.Children.Clear();
            _SelectedItemHistory.Clear();

            // Load Series into lvBrowser_left;
            lvBrowser_left.Items.Clear();

            List<Objects.Series> lAvailableSeries = Objects.Series.getAllSeries();

            if (lAvailableSeries != null && lAvailableSeries.Count > 0)
            {
                foreach (Objects.Series oShow in lAvailableSeries)
                {
                    ListViewItem lviShow = new ListViewItem();
                    lviShow.Content = oShow.Name;
                    lviShow.Tag = oShow;
                    lviShow.Selected += new RoutedEventHandler(lviShow_Selected);

                    lvBrowser_left.Items.Add(lviShow);
                }
            }


        }

        void lviShow_Selected(object sender, RoutedEventArgs e)
        {
            ListViewItem lviShow = (ListViewItem)sender;

            Objects.Series oShow = (Objects.Series)lviShow.Tag;

            if (oShow != null && oShow.SeriesID > 0)
            {
                seriesSelected(oShow.SeriesID);
            }
        }

        private void tvLibrary_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            /*
            // Clear Item-Details...
            spnItemDetails.Children.Clear();
            lvBrowser_left.Items.Clear();
            _SelectedItemHistory.Clear();
             * */

            if (tvLibrary.SelectedItem != null)
            {
                TreeViewItem tviSelectedItem = (TreeViewItem)tvLibrary.SelectedItem;
                
                if (tviSelectedItem.Tag != null && tviSelectedItem.Tag.GetType() == typeof(Objects.SeriesSeason)) // Serie's Season Selected
                {
                    // Setup a new Season-Object.
                    Objects.SeriesSeason oNewSeason = new Objects.SeriesSeason();

                    // Load Season's Episodes in lvBrowser_left.
                    lvBrowser_left.Items.Clear();

                    Objects.SeriesSeason oSeason = (Objects.SeriesSeason)tviSelectedItem.Tag;
                    if (oSeason != null && oSeason.SeasonID > 0)
                    {
                        if (oSeason.Episodes != null && oSeason.Episodes.Count > 0)
                        {
                            foreach (Objects.SeriesEpisode oEpisode in oSeason.Episodes)
                            {
                                // Check if episode was seen by selected audience.
                                List<Objects.PlaybackHistoryRecord> lPlaybackHistory = Objects.PlaybackHistoryRecord.getAllRecords(2, oEpisode.EpisodeID);
                                bool bWasSeen = false;

                                foreach (Objects.PlaybackHistoryRecord oRecord in lPlaybackHistory)
                                {
                                    if (oRecord.AudienceID == SelectedAudition.AuditionID)
                                        bWasSeen = true;
                                }

                                string sEpisodeTitle = String.Empty;
                                if (oEpisode.EpisodeNo < 10)
                                    sEpisodeTitle = "E0" + oEpisode.EpisodeNo.ToString();
                                else
                                    sEpisodeTitle = "E" + oEpisode.EpisodeNo.ToString();

                                ListViewItem lviEpisode = new ListViewItem();
                                lviEpisode.Content = sEpisodeTitle + " - " + oEpisode.Name;
                                lviEpisode.Tag = oEpisode;
                                lviEpisode.MouseDoubleClick += new MouseButtonEventHandler(lviEpisode_MouseDoubleClick);
                                lviEpisode.Selected +=new RoutedEventHandler(lviEpisode_Selected);

                                if (bWasSeen)
                                {
                                    lviEpisode.Content = "√ " + lviEpisode.Content;
                                    lviEpisode.Foreground = Brushes.DarkGreen;
                                    lviEpisode.FontStyle = FontStyles.Italic;
                                }

                                lvBrowser_left.Items.Add(lviEpisode);
                            }
                        }
                    }
                }
            }
        }

        Objects.MediaInfo CurrentPlayback { get; set; }
        bool IsPlaying { get; set; }

        void lviEpisode_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (IsPlaying)
            {
                MessageBox.Show("Es läuft bereits eine Wiedergabe! Beenden Sie zuerst das laufende Video.", "Parallele Wiedergaben", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                return;
            }

            IsPlaying = true;

            ListViewItem lviSelectedEpisode = (ListViewItem)sender;
            Objects.SeriesEpisode oEpisode = (Objects.SeriesEpisode)lviSelectedEpisode.Tag;
            Objects.SeriesSeason oSeason = new Objects.SeriesSeason(oEpisode.SeasonID);

            updateStatus("Es läuft: " + Objects.Series.getTitle(oEpisode.SeriesID) + " - S" + oSeason.Number.ToString() + " E" + oEpisode.EpisodeNo.ToString() + " - " + oEpisode.Name, true);

            CurrentPlayback = new Objects.MediaInfo();
            CurrentPlayback.FullPath = oEpisode.MediaFile;
            CurrentPlayback.UserdefinedMediaInfo = oEpisode;
            CurrentPlayback.MediaType = 1;

            ParameterizedThreadStart oThreadStart = new ParameterizedThreadStart(startVLCPlayerEpisode);
            Thread thEpisodePlayback = new Thread(oThreadStart);
            thEpisodePlayback.Start(oEpisode);
        }

        public void startVLCPlayerEpisode(Object oEpisode)
        {
            Objects.SeriesEpisode Episode = (Objects.SeriesEpisode)oEpisode;

            if (System.IO.File.Exists(Episode.MediaFile) == false)
            {
                // Drop CurrentPlayback-Value & Playback-Status.
                CurrentPlayback = null;
                IsPlaying = false;
                MessageBox.Show("Die Datei \"" + Episode.MediaFile + "\" wurde nicht gefunden!", "Medium nicht gefunden", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            if (System.IO.File.Exists(oSettings.VLCExecutablePath) == false)
            {
                CurrentPlayback = null;
                IsPlaying = false;
                MessageBox.Show("Das angegebene Abspielprogram (\"" + oSettings.VLCExecutablePath + "\") wurde nicht gefunden! Bitte überprüfen Sie Ihre Einstellungen!", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }


            System.Diagnostics.Process pVLCPlayer = new System.Diagnostics.Process();
            pVLCPlayer.StartInfo = new System.Diagnostics.ProcessStartInfo();
            pVLCPlayer.StartInfo.FileName = oSettings.VLCExecutablePath;
            if (oSettings.VideoPlayerExtensions == 1)
            {
                pVLCPlayer.StartInfo.Arguments = "--fullscreen --play-and-exit ";
            }
            pVLCPlayer.StartInfo.Arguments += "\"" + Episode.MediaFile + "\"";
            pVLCPlayer.Start();

            pVLCPlayer.WaitForExit();

            // Create playback record.
            Objects.PlaybackHistoryRecord.CreateRecord(SelectedAudition.AuditionID, 2, Episode.EpisodeID);

            // Reload Playback-History.
            Dispatcher.Invoke(new getEpisodeHistoryCallback(getEpisodeHistory), new object[] { Episode });

            // Refresh Item State.
            Dispatcher.Invoke(new setSeenCallback(setSeen));

            // Update Audition.
            SelectedAudition.LastMediaID = Episode.EpisodeID;
            SelectedAudition.LastMediaType = 2;
            SelectedAudition.SaveChanges();

            // Drop CurrentPlayback-Value & Playback-Status.
            CurrentPlayback = null;
            IsPlaying = false;

            // Toggle Status.
            this.Dispatcher.Invoke(new updateStatusCallback(updateStatus), new object[] { "Bereit...", false });
        }

        private void setSeen()
        {
            if (lvBrowser_left.SelectedIndex > -1)
            {
                ListViewItem lviSelectedItem = (ListViewItem)lvBrowser_left.SelectedItem;
                int iSelectedIndex = lvBrowser_left.SelectedIndex;
                lviSelectedItem.Foreground = Brushes.DarkGreen;
                lviSelectedItem.FontStyle = FontStyles.Italic;
                lviSelectedItem.Content = "√ " + lviSelectedItem.Content;

                //lvBrowser_left.Items[iSelectedIndex] = lviSelectedItem;
                lvBrowser_left.Items.RemoveAt(iSelectedIndex);
                lvBrowser_left.Items.Insert(iSelectedIndex, lviSelectedItem);

                lvBrowser_left.Items.Refresh();
            }
        }

        private delegate void setSeenCallback();

        int CurrentMovieFileCount { get; set; }

        public void startVLCPlayerMovie(Object Data)
        {
            Object[] Movie = (Object[])Data;

            Objects.Movie oMovie = (Objects.Movie)Movie[0];
            Objects.Genre oGenre = new Objects.Genre(oMovie.GenreID);
            int iFileCount = (int)Movie[1];

            if (oMovie.Files.Count < iFileCount)
                return;

            if (System.IO.File.Exists(oMovie.Files[iFileCount].Replace(";", "")) == false)
            {
                // Drop CurrentPlayback-Value & Playback-Status.
                CurrentPlayback = null;
                IsPlaying = false;
                MessageBox.Show("Die Datei \"" + oMovie.Files[iFileCount].Replace(";", "") + "\" wurde nicht gefunden!", "Medium nicht gefunden", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            if (System.IO.File.Exists(oSettings.VLCExecutablePath) == false)
            {
                CurrentPlayback = null;
                IsPlaying = false;
                MessageBox.Show("Das angegebene Abspielprogram (\"" + oSettings.VLCExecutablePath + "\") wurde nicht gefunden! Bitte überprüfen Sie Ihre Einstellungen!", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            Dispatcher.Invoke(new updateStatusCallback(updateStatus), new object[] { "Es läuft: " + oMovie.Name + " (" + oGenre.Name + ", " + oMovie.Year + ") [" + (iFileCount + 1).ToString() + "/" + oMovie.Files.Count.ToString() + "]", true });

            if (System.IO.File.Exists(oSettings.VLCExecutablePath))
            {
                System.Diagnostics.Process pVLCPlayer = new System.Diagnostics.Process();
                pVLCPlayer.StartInfo = new System.Diagnostics.ProcessStartInfo();
                pVLCPlayer.StartInfo.FileName = oSettings.VLCExecutablePath;
                pVLCPlayer.StartInfo.Arguments = "--fullscreen --play-and-exit \"" + oMovie.Files[iFileCount].Replace(";", "") + "\"";
                pVLCPlayer.Start();

                pVLCPlayer.WaitForExit();
            }
            else
            {
                MessageBox.Show("Die Video-Player-Anwendung wurde nicht in \"" + oSettings.VLCExecutablePath + "\" gefunden!", "Kein Video-Player gefunden", MessageBoxButton.OK, MessageBoxImage.Error);
            }

            // Check for additional files and play if any.
            if (iFileCount < (oMovie.Files.Count - 1))
            {
                ++iFileCount;
                startVLCPlayerMovie(new object[] {oMovie, iFileCount});
                return;
            }

            // Create playback record.
            Objects.PlaybackHistoryRecord.CreateRecord(SelectedAudition.AuditionID, 1, oMovie.MovieID);

            // Reload Playback-History.
            Dispatcher.Invoke(new getMovieHistoryCallback(getMovieHistory), new object[] { oMovie });
            //getMovieHistory(oMovie);

            // Update Audition.
            SelectedAudition.LastMediaID = oMovie.MovieID;
            SelectedAudition.LastMediaType = 1;
            SelectedAudition.SaveChanges();

            // Drop CurrentPlayback-Value & Playback-Status.
            CurrentPlayback = null;
            IsPlaying = false;

            // Toggle Status.
            this.Dispatcher.Invoke(new updateStatusCallback(updateStatus), new object[] { "Bereit...", false });
        }

        public void updateStatus(string sNewStatusMessage, bool bEnableProgressAnimation)
        {
            this.Title = "XMM - " + sNewStatusMessage;
            lblStatus.Content = sNewStatusMessage;
            pbStatus.IsIndeterminate = bEnableProgressAnimation;
        }

        public delegate void updateStatusCallback(string sNewStatusMessage, bool bEnableProgressAnimation);

        private void cmbAuditionSelection_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (cmbAuditionSelection.SelectedIndex > -1)
            {
                SelectedAudition = (Objects.Audition)cmbAuditionSelection.SelectedItem;
                oSettings.LastAuditionID = SelectedAudition.AuditionID;
                oSettings.Save();
                //RefreshXMM();

                // Refresh Data;
                lvBrowser_left.ItemsSource = null;
                lvBrowser_left.Items.Clear();

                /*
                // Change connection-string if neccessary.
                System.Configuration.ConnectionStringSettings oConnection = System.Configuration.ConfigurationManager.ConnectionStrings[0];
                oConnection.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|" + oSettings.DatabaseStoragePath + ";Integrated Security=True;Connect Timeout=30;User Instance=True";
                */

                updateConnectionString();

                updateLibraryTopItems();
                testConnection();

                // Load Movies.
                loadMovies();

                // Load Series.
                loadSeries();
            }
        }

        private void mitDeleteSelectedItem_Click(object sender, RoutedEventArgs e)
        {
            ListViewItem lviSelectedItem = (ListViewItem)lvBrowser_left.SelectedItem;
            if (lvBrowser_left.SelectedIndex > -1 && lviSelectedItem.Tag.GetType() == typeof(Objects.SeriesEpisode))
            {
                Objects.SeriesEpisode oSelectedEpisode = (Objects.SeriesEpisode)lviSelectedItem.Tag;

                if (oSelectedEpisode != null && oSelectedEpisode.EpisodeID != 0)
                {
                    Objects.SeriesSeason oSelectedEpisodeSeason = new Objects.SeriesSeason(oSelectedEpisode.SeasonID);
                    if (MessageBox.Show("Möchten Sie \"" + Objects.Series.getTitle(oSelectedEpisode.SeriesID) + "\" (S" + oSelectedEpisodeSeason.SeasonID.ToString() + " E" + oSelectedEpisode.EpisodeNo.ToString() + ") wirklich löschen?", "Folge löschen?", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
                    {
                        Objects.SeriesEpisode.Delete(oSelectedEpisode.EpisodeID);
                        RefreshXMM();
                    }
                }
            }
            else if (lvBrowser_left.SelectedIndex > -1 && lviSelectedItem.Tag.GetType() == typeof(Int32))
            {
                Objects.Movie oSelectedMovie = new Objects.Movie((int)lviSelectedItem.Tag);

                if (oSelectedMovie != null && oSelectedMovie.MovieID != 0)
                {
                    if (MessageBox.Show("Möchten Sie \"" + oSelectedMovie.Name + "\" (" + oSelectedMovie.Year.ToString() + ") wirklich löschen?", "Film löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
                    {
                        Objects.Movie.Delete(oSelectedMovie.MovieID);
                        RefreshXMM();
                    }
                }
            }
        }

        private void mitSettings_Click(object sender, RoutedEventArgs e)
        {
            //Dialoges.SetupSettings dlgSettings = new Dialoges.SetupSettings();
            //dlgSettings.ShowDialog();
        }

        private void tviLibrary_Selected(object sender, RoutedEventArgs e)
        {
            /*
            // Clear Item-Details...
            spnItemDetails.Children.Clear();
            lvBrowser_left.Items.Clear();
            _SelectedItemHistory.Clear();
             * */

            if (tvLibrary.Items.IndexOf(tvLibrary.SelectedItem) != -1)
            {
                spnItemDetails.Children.Clear();
                lvBrowser_left.Items.Clear();
                _SelectedItemHistory.Clear();
            }
        }

        private void mitAbout_Click(object sender, RoutedEventArgs e)
        {
            About dlgAbout = new About();
            dlgAbout.ShowDialog();
        }

        private void tsbShowChronics_Click(object sender, RoutedEventArgs e)
        {
            //Dialoges.Library.HistoryViewer dlgHistoryViewer = new Dialoges.Library.HistoryViewer(this);
            //dlgHistoryViewer.ShowDialog();
        }

        private void btnManageAudiences_Click(object sender, RoutedEventArgs e)
        {
            //Dialoges.ManageAudiences dlgAudienceManager = new Dialoges.ManageAudiences(this);
            //dlgAudienceManager.ShowDialog();
        }
    }
}
